#include "infowindow.h"
#include "ui_infowindow.h"
#include <QTextStream>

const int cubeTimerInt = 20;


InfoWindow::InfoWindow(ProgressListener *pl, IFileBuffer *fb) :
    ui(new Ui::InfoWindow),
    needHide(false)
{
    ui->setupUi(this);
    connect(pl, SIGNAL(updateInfo(ProgressListener::Info)), SLOT(onInfoUpdate(ProgressListener::Info)));

    connect(fb, SIGNAL(beginFileLoading(qint64)), SLOT(onFileLoadingBegin()));
    connect(fb, SIGNAL(beginFileSaving(qint64)), SLOT(onFileSavingBegin()));
    connect(fb, SIGNAL(opPaused()), SLOT(onOpPaused()));
    connect(fb, SIGNAL(opResumed()), SLOT(onOpResumed()));
    connect(fb, SIGNAL(fileLoaded(QString,qint64)), SLOT(onOpFinished()));
    connect(fb, SIGNAL(fileLoadingError(QString,QString,IFileBuffer::State)), SLOT(onOpFinished()));
    connect(fb, SIGNAL(fileSaved(QString)), SLOT(onOpFinished()));
    connect(fb, SIGNAL(fileSavingError(QString,QString)), SLOT(onOpFinished()));

    connect(ui->pauseResumeButton, SIGNAL(clicked()), fb, SLOT(trigger()));
    connect(ui->stopButton, SIGNAL(clicked()), fb, SLOT(stop()));    

    cube = new GLWidget(this);
    cube->setMinimumHeight(150);
    cube->rotateBy(+42 * 16, +42 * 16, -21 * 16);
    ui->verticalLayout->addWidget(cube);

    connect(cube, SIGNAL(stopped()), SLOT(onCubeStopped()));
}

InfoWindow::~InfoWindow()
{
    delete ui;
}

void InfoWindow::onFileLoadingBegin()
{
    cube->setDirection(GLWidget::CLOCKWISE);
    showView();
}

void InfoWindow::onFileSavingBegin()
{
    cube->setDirection(GLWidget::COUNTER_CLOCKWISE);
    showView();
}

void InfoWindow::showView()
{
    needHide = false;
    onOpResumed();
    show();
}

void InfoWindow::onInfoUpdate(ProgressListener::Info info)
{
    ui->progressBar->setValue(info.progressVal);
    ui->bytesProcessedEdit->setText(convertBytes(info.bytesProcessed));
    ui->timeElapsedEdit->setText(convertTime(info.timeElapsed));
    ui->curSpeedEdit->setText(convertSpeed(info.curSpeed));
    ui->avgSpeedEdit->setText(convertSpeed(info.avgSpeed));
    ui->timeRemainEdit->setText(convertTime(info.timeRemaining));
}

void InfoWindow::onOpPaused()
{
    ui->pauseResumeButton->setText(tr("Возобновить"));    
    cube->stop();
}

void InfoWindow::onOpResumed()
{
    ui->pauseResumeButton->setText(tr("Приостановить"));
    cube->start();
}

void InfoWindow::onOpFinished()
{
    needHide = true;
    cube->stop();
}

void InfoWindow::onCubeStopped()
{
    if(needHide){
        hide();
    }
}

QString InfoWindow::convertBytes(qint64 bytesCount){
    static QString units[] = {tr("Б"), tr("КБ"), tr("МБ")};
    int i;
    for(i = 0; i<2; i++){
        if(bytesCount <= 1024){
            break;
        } else {
            bytesCount /= 1024;
        }
    }
    return QString::number(bytesCount) + " " + units[i];
}

QString InfoWindow::convertSpeed(qint64 speed)
{
    return convertBytes(speed * 1000) + tr("/с");
}

QString InfoWindow::convertTime(qint64 time)
{
    QString formattedTime;
    static QString labels[] = {tr("с"), tr("."), tr("м "), tr("ч ")};
    static int factors[] = {1000, 60, 60, 60};
    int values[4];
    for(int i = 0; i<4; i++){
        values[i] = time % factors[i];
        time /= factors[i];
    }
    int start;
    for(start = 3; start>1; start--)
    {
        if(values[start] > 0)
            break;
    }
    QTextStream builder(&formattedTime);
    for(int i = start; i>=0; i--){
        builder << values[i] << labels[i];
    }

    return formattedTime;
}
